home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / bin / purple-url-handler < prev    next >
Text File  |  2009-10-14  |  12KB  |  395 lines

  1. #!/usr/bin/env python
  2.  
  3. import dbus
  4. import re
  5. import sys
  6. import time
  7. import urllib
  8.  
  9. bus = dbus.SessionBus()
  10. obj = None
  11. try:
  12.     obj = bus.get_object("im.pidgin.purple.PurpleService",
  13.                          "/im/pidgin/purple/PurpleObject")
  14. except dbus.DBusException, e:
  15.     if e._dbus_error_name == "org.freedesktop.DBus.Error.ServiceUnknown":
  16.         print "Error: no libpurple-powered client is running. Try starting Pidgin or Finch."
  17.         sys.exit(1)
  18. purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
  19.  
  20. class CheckedObject:
  21.     def __init__(self, obj):
  22.         self.obj = obj
  23.  
  24.     def __getattr__(self, attr):
  25.         return CheckedAttribute(self, attr)
  26.  
  27. class CheckedAttribute:
  28.     def __init__(self, cobj, attr):
  29.         self.cobj = cobj
  30.         self.attr = attr
  31.  
  32.     def __call__(self, *args):
  33.         # Redirect stderr to suppress the printing of an " Introspect error"
  34.         # message if nothing is listening on the bus.  We print a friendly
  35.         # error message ourselves.
  36.         real_stderr = sys.stderr
  37.         sys.stderr = None
  38.         result = self.cobj.obj.__getattr__(self.attr)(*args)
  39.         sys.stderr = real_stderr
  40.  
  41. # This can be useful for debugging.
  42. #        if (result == 0):
  43. #            print "Error: " + self.attr + " " + str(args) + " returned " + str(result)
  44.  
  45.         return result
  46.  
  47. cpurple = CheckedObject(purple)
  48.  
  49. def extendlist(list, length, fill):
  50.     if len(list) < length:
  51.         return list + [fill] * (length - len(list))
  52.     else:
  53.         return list
  54.  
  55. def convert(value):
  56.     try:
  57.         return int(value)
  58.     except:
  59.         return value
  60.  
  61. def account_not_found():
  62.     print "No matching account found."
  63.     sys.exit(1)
  64.  
  65. def bring_account_online(account):
  66.     if not cpurple.PurpleAccountIsConnected(account):
  67.         # The last argument is meant to be a GList * but the D-Bus binding
  68.         # generator thing just wants a UInt32, which is pretty failing.
  69.         # Happily, passing a 0 to mean an empty list turns out to work anyway.
  70.         purple.PurpleAccountSetStatusList(account, "online", 1, 0)
  71.         purple.PurpleAccountConnect(account)
  72.  
  73. def findaccount(protocolname, accountname="", matcher=None):
  74.     if matcher:
  75.         for account in cpurple.PurpleAccountsGetAll():
  76.             if accountname != "" and accountname != cpurple.PurpleAccountGetUsername(a):
  77.                 continue
  78.             if matcher(account):
  79.                 bring_account_online(account)
  80.                 return account
  81.         account_not_found()
  82.  
  83.     # prefer connected accounts
  84.     account = cpurple.PurpleAccountsFindConnected(accountname, protocolname)
  85.     if (account != 0):
  86.         return account
  87.  
  88.     # try to get any account and connect it
  89.     account = cpurple.PurpleAccountsFindAny(accountname, protocolname)
  90.     if (account == 0):
  91.         account_not_found()
  92.  
  93.     bring_account_online(account)
  94.     return account
  95.  
  96. def goim(account, screenname, message=None):
  97.     # XXX: 1 == PURPLE_CONV_TYPE_IM
  98.     conversation = cpurple.PurpleConversationNew(1, account, screenname)
  99.     if message:
  100.         purple.PurpleConvSendConfirm(conversation, message)
  101.  
  102. def gochat(account, params, message=None):
  103.     connection = cpurple.PurpleAccountGetConnection(account)
  104.     purple.ServJoinChat(connection, params)
  105.  
  106.     if message != None:
  107.         for i in range(20):
  108.             # XXX: 2 == PURPLE_CONV_TYPE_CHAT
  109.             conversation = purple.PurpleFindConversationWithAccount(2, params.get("channel", params.get("room")), account)
  110.             if conversation:
  111.                 purple.PurpleConvSendConfirm(conversation, message)
  112.                 break
  113.             else:
  114.                 time.sleep(0.5)
  115.  
  116. def addbuddy(account, screenname, group="", alias=""):
  117.     cpurple.PurpleBlistRequestAddBuddy(account, screenname, group, alias)
  118.  
  119.  
  120. def aim(uri):
  121.     protocol = "prpl-aim"
  122.     match = re.match(r"^aim:([^?]*)(\?(.*))", uri)
  123.     if not match:
  124.         print "Invalid aim URI: %s" % uri
  125.         return
  126.  
  127.     command = urllib.unquote_plus(match.group(1))
  128.     paramstring = match.group(3)
  129.     params = {}
  130.     if paramstring:
  131.         for param in paramstring.split("&"):
  132.             key, value = extendlist(param.split("=", 1), 2, "")
  133.             params[key] = urllib.unquote_plus(value)
  134.     accountname = params.get("account", "")
  135.     screenname = params.get("screenname", "")
  136.  
  137.     account = findaccount(protocol, accountname)
  138.  
  139.     if command.lower() == "goim":
  140.         goim(account, screenname, params.get("message"))
  141.     elif command.lower() == "gochat":
  142.         gochat(account, params)
  143.     elif command.lower() == "addbuddy":
  144.         addbuddy(account, screenname, params.get("group", ""))
  145.  
  146. def gg(uri):
  147.     protocol = "prpl-gg"
  148.     match = re.match(r"^gg:(.*)", uri)
  149.     if not match:
  150.         print "Invalid gg URI: %s" % uri
  151.         return
  152.  
  153.     screenname = urllib.unquote_plus(match.group(1))
  154.     account = findaccount(protocol)
  155.     goim(account, screenname)
  156.  
  157. def icq(uri):
  158.     protocol = "prpl-icq"
  159.     match = re.match(r"^icq:([^?]*)(\?(.*))", uri)
  160.     if not match:
  161.         print "Invalid icq URI: %s" % uri
  162.         return
  163.  
  164.     command = urllib.unquote_plus(match.group(1))
  165.     paramstring = match.group(3)
  166.     params = {}
  167.     if paramstring:
  168.         for param in paramstring.split("&"):
  169.             key, value = extendlist(param.split("=", 1), 2, "")
  170.             params[key] = urllib.unquote_plus(value)
  171.     accountname = params.get("account", "")
  172.     screenname = params.get("screenname", "")
  173.  
  174.     account = findaccount(protocol, accountname)
  175.  
  176.     if command.lower() == "goim":
  177.         goim(account, screenname, params.get("message"))
  178.     elif command.lower() == "gochat":
  179.         gochat(account, params)
  180.     elif command.lower() == "addbuddy":
  181.         addbuddy(account, screenname, params.get("group", ""))
  182.  
  183. def irc(uri):
  184.     protocol = "prpl-irc"
  185.     match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri)
  186.     if not match:
  187.         print "Invalid irc URI: %s" % uri
  188.         return
  189.  
  190.     server = urllib.unquote_plus(match.group(2)) or ""
  191.     target = match.group(3) or ""
  192.     query = match.group(5) or ""
  193.  
  194.     modifiers = {}
  195.     if target:
  196.         for modifier in target.split(",")[1:]:
  197.             modifiers[modifier] = True
  198.  
  199.     isnick = modifiers.has_key("isnick")
  200.  
  201.     paramstring = match.group(5)
  202.     params = {}
  203.     if paramstring:
  204.         for param in paramstring.split("&"):
  205.             key, value = extendlist(param.split("=", 1), 2, "")
  206.             params[key] = urllib.unquote_plus(value)
  207.  
  208.     def correct_server(account):
  209.         username = cpurple.PurpleAccountGetUsername(account)
  210.         return ("@" in username) and (server == (username.split("@"))[1])
  211.  
  212.     account = findaccount(protocol, matcher=correct_server)
  213.  
  214.     if (target != ""):
  215.         if (isnick):
  216.             goim(account, urllib.unquote_plus(target.split(",")[0]), params.get("msg"))
  217.         else:
  218.             channel = urllib.unquote_plus(target.split(",")[0])
  219.             if channel[0] != "#":
  220.                 channel = "#" + channel
  221.             gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg"))
  222.  
  223. def msnim(uri):
  224.     protocol = "prpl-msn"
  225.     match = re.match(r"^msnim:([^?]*)(\?(.*))", uri)
  226.     if not match:
  227.         print "Invalid msnim URI: %s" % uri
  228.         return
  229.  
  230.     command = urllib.unquote_plus(match.group(1))
  231.     paramstring = match.group(3)
  232.     params = {}
  233.     if paramstring:
  234.         for param in paramstring.split("&"):
  235.             key, value = extendlist(param.split("=", 1), 2, "")
  236.             params[key] = urllib.unquote_plus(value)
  237.     screenname = params.get("contact", "")
  238.  
  239.     account = findaccount(protocol)
  240.  
  241.     if command.lower() == "chat":
  242.         goim(account, screenname)
  243.     elif command.lower() == "add":
  244.         addbuddy(account, screenname)
  245.  
  246. def myim(uri):
  247.         protocol = "prpl-myspace"
  248.         print "TODO: send uri: ", uri
  249.         assert False, "Not implemented"
  250.  
  251. def sip(uri):
  252.     protocol = "prpl-simple"
  253.     match = re.match(r"^sip:(.*)", uri)
  254.     if not match:
  255.         print "Invalid sip URI: %s" % uri
  256.         return
  257.  
  258.     screenname = urllib.unquote_plus(match.group(1))
  259.     account = findaccount(protocol)
  260.     goim(account, screenname)
  261.  
  262. def xmpp(uri):
  263.     protocol = "prpl-jabber"
  264.     match = re.match(r"^xmpp:(//([^/?#]*)/?)?([^?#]*)(\?([^;#]*)(;([^#]*))?)?(#(.*))?", uri)
  265.     if not match:
  266.         print "Invalid xmpp URI: %s" % uri
  267.         return
  268.  
  269.     tmp = match.group(2)
  270.     if (tmp):
  271.         accountname = urllib.unquote_plus(tmp)
  272.     else:
  273.         accountname = ""
  274.  
  275.     screenname = urllib.unquote_plus(match.group(3))
  276.  
  277.     tmp = match.group(5)
  278.     if (tmp):
  279.         command = urllib.unquote_plus(tmp)
  280.     else:
  281.         command = ""
  282.  
  283.     paramstring = match.group(7)
  284.     params = {}
  285.     if paramstring:
  286.         for param in paramstring.split(";"):
  287.             key, value = extendlist(param.split("=", 1), 2, "")
  288.             params[key] = urllib.unquote_plus(value)
  289.  
  290.     account = findaccount(protocol, accountname)
  291.  
  292.     if command.lower() == "message":
  293.         goim(account, screenname, params.get("body"))
  294.     elif command.lower() == "join":
  295.         room, server = screenname.split("@")
  296.         gochat(account, {"room": room, "server": server})
  297.     elif command.lower() == "roster":
  298.         addbuddy(account, screenname, params.get("group", ""), params.get("name", ""))
  299.     else:
  300.         goim(account, screenname)
  301.  
  302. def gtalk(uri):
  303.     protocol = "prpl-jabber"
  304.     match = re.match(r"^gtalk:([^?]*)(\?(.*))", uri)
  305.     if not match:
  306.         print "Invalid gtalk URI: %s" % uri
  307.         return
  308.  
  309.     command = urllib.unquote_plus(match.group(1))
  310.     paramstring = match.group(3)
  311.     params = {}
  312.     if paramstring:
  313.         for param in paramstring.split("&"):
  314.             key, value = extendlist(param.split("=", 1), 2, "")
  315.             params[key] = urllib.unquote_plus(value)
  316.     accountname = params.get("from_jid", "")
  317.     jid = params.get("jid", "")
  318.  
  319.     account = findaccount(protocol, accountname)
  320.  
  321.     if command.lower() == "chat":
  322.         goim(account, jid)
  323.     elif command.lower() == "call":
  324.         # XXX V&V prompt to establish call
  325.         goim(account, jid)
  326.  
  327. def ymsgr(uri):
  328.     protocol = "prpl-yahoo"
  329.     match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri)
  330.     if not match:
  331.         print "Invalid ymsgr URI: %s" % uri
  332.         return
  333.  
  334.     command = urllib.unquote_plus(match.group(1))
  335.     screenname = urllib.unquote_plus(match.group(3))
  336.     paramstring = match.group(5)
  337.     params = {}
  338.     if paramstring:
  339.         for param in paramstring.split("&"):
  340.             key, value = extendlist(param.split("=", 1), 2, "")
  341.             params[key] = urllib.unquote_plus(value)
  342.  
  343.     account = findaccount(protocol)
  344.  
  345.     if command.lower() == "sendim":
  346.         goim(account, screenname, params.get("m"))
  347.     elif command.lower() == "chat":
  348.         gochat(account, {"room": screenname})
  349.     elif command.lower() == "addfriend":
  350.         addbuddy(account, screenname)
  351.  
  352.  
  353. def main(argv=sys.argv):
  354.     if len(argv) != 2 or argv[1] == "--help" or argv[1] == "-h":
  355.         print "Usage: %s URI" % argv[0]
  356.         print "Example: %s \"xmpp:romeo@montague.net?message\"" % argv[0]
  357.  
  358.         if len(argv) != 2:
  359.             sys.exit(1)
  360.         else:
  361.             return 0
  362.  
  363.     uri = argv[1]
  364.     type = uri.split(":")[0]
  365.  
  366.     try:
  367.         if type == "aim":
  368.             aim(uri)
  369.         elif type == "gg":
  370.             gg(uri)
  371.         elif type == "icq":
  372.             icq(uri)
  373.         elif type == "irc":
  374.             irc(uri)
  375.         elif type == "msnim":
  376.             msnim(uri)
  377.         elif type == "myim":
  378.             myim(uri)
  379.         elif type == "sip":
  380.             sip(uri)
  381.         elif type == "xmpp":
  382.             xmpp(uri)
  383.         elif type == "gtalk":
  384.             gtalk(uri)
  385.         elif type == "ymsgr":
  386.             ymsgr(uri)
  387.         else:
  388.             print "Unknown protocol: %s" % type
  389.     except dbus.DBusException, e:
  390.         print "Error: %s" % (e.message)
  391.         sys.exit(1)
  392.  
  393. if __name__ == "__main__":
  394.     main()
  395.